library ArtificialIntelligence initializer init requires TextSystem, NOTDAWorldPhysics

	/*

	Point Value 98 : Civilians
	Point Value 13 : Convoy
	Point Value 12 : Marines
	Point Value 11: Roshan/K-9

	*/
	function AIMarineFilter takes nothing returns boolean
		return IsUnitType(GetFilterUnit(),UNIT_TYPE_ANCIENT)==false and IsUnitAlly(GetFilterUnit(),Player(13))==true
	endfunction

	function AIMarine_GetRandUnit takes nothing returns unit
		local group g = GetUnitsInRectMatching(bj_mapInitialPlayableArea, Condition(function AIMarineFilter))
		set udg_AIMarineTarget = GroupPickRandomUnit(g)
		call DestroyGroup(g)
		set g = null
		return udg_AIMarineTarget
	endfunction

	function PoisonCheck takes unit u returns boolean
		return GetUnitAbilityLevel(u,'B008')>0 or GetUnitAbilityLevel(u,'Bpoi')>0 or GetUnitAbilityLevel(u,'Bpsd')>0 or GetUnitAbilityLevel(u,'B00B')>0 or GetUnitAbilityLevel(u,'BNpa')>0 or GetUnitAbilityLevel(u,'Bapl')>0
	endfunction

	function AilmentCheck takes unit u returns boolean
		return PoisonCheck(u) or GetUnitAbilityLevel(u,'B00A')>0 or GetWidgetLife(u)<200
	endfunction

	function SelectAlliedUnits takes nothing returns boolean
		local integer i = GetUnitPointValue(GetFilterUnit())
		return i==10 or i==11 or i==12 or i==13 or i==99 or i==98
	endfunction

	function IsCivilian takes unit u returns boolean
		return GetUnitPointValue(u)==98
	endfunction

	function ItemAI takes unit u returns nothing
		local unit u2
		local location l = GetUnitLoc(u)
		local item i
		local group g = AMGetUnitsInRange(800,l,Condition(function SelectAlliedUnits))
		call RemoveLocation(l)
		set l = null
		if (GetUnitAbilityLevel(u,'B00A')>0 and GetWidgetLife(u)<=330.0) or GetWidgetLife(u)<=80.0 then
			set i = GetUnitItem(u,'phea')
			if i!=null then
				call UnitUseItem(u,i) //Fibrin
				if IsCivilian(u) and GetItemCharges(i)>0 then
					call TriggerSleepAction(0.)
					call UnitRemoveItem(u,i)
				endif
			endif
		endif
		if PoisonCheck(u) then
			set i = GetUnitItem(u,'I00J')
			if i!=null then
				call UnitUseItem(u,i) // Anti-Venom

				if IsCivilian(u) and GetItemCharges(i)>0 then
					call TriggerSleepAction(0.)
					call UnitRemoveItem(u,i)
				endif
			endif
		endif
		loop
			set u2 = FirstOfGroup(g)
			exitwhen u2==null
			if GetWidgetLife(u2)<240.0 and GetUnitAbilityLevel(u2,'Brej')<=0 and GetUnitAbilityLevel(u2,'B00H')<=0 then
				call UnitUseItemTarget(u,GetUnitItem(u,'I004'),u2)
				exitwhen 1==1
			endif
			call GroupRemoveUnit(g,u2)
		endloop
		call DestroyGroup(g)
		set g = null
		set u2 = null
		set i = null
	endfunction

	function CorpsmanAI takes unit corpsman returns boolean
		local unit u
		local location l = GetUnitLoc(corpsman)
		local group g = AMGetUnitsInRange(1200, l, Condition(function SelectAlliedUnits))
		local boolean rval
		
		loop
			set u = FirstOfGroup(g)
			exitwhen u==null
			set rval = AilmentCheck(u) 
			if rval then
				call UnitResetCooldown(corpsman)
				if PoisonCheck(u) or GetUnitAbilityLevel(u,'Bapl')>0 then
					call IssueTargetOrder(corpsman,"banish",u)
				elseif GetUnitAbilityLevel(u,'B00A')>0 and GetWidgetLife(u)>20.0 then
					call IssueTargetOrder(corpsman,"cripple",u)
				elseif GetWidgetLife(u)<200.0 and GetUnitAbilityLevel(u,'Brej')<=0 and GetUnitAbilityLevel(u,'B00H')<=0 then
					call IssueTargetOrder(corpsman,"rejuvination",u)
				endif
				if GetRandomInt(0,2)==1 and u!=corpsman then
					call FieldChat(corpsman, 3.0, "|cfff3ad00Corpsman|r : I'm on it." )
				endif
				set u = null
				exitwhen 1==1
			endif
			call GroupRemoveUnit(g,u)
		endloop

		call DestroyGroup(g)
		call RemoveLocation(l)
		set l = null
		set g = null
		return rval
	endfunction

	//===========
	// Convoy AI
	//===========
	
	function CASPatrol takes nothing returns nothing
		call IssuePointOrder(GetEnumUnit(),"patrol",GetRandomReal(GetRectMinX(bj_mapInitialPlayableArea),GetRectMaxX(bj_mapInitialPlayableArea)),GetRandomReal(GetRectMinY(bj_mapInitialPlayableArea),GetRectMaxY(bj_mapInitialPlayableArea)))
	endfunction

	function EngineerOrders takes nothing returns nothing
		local unit u = GetEnumUnit()
		call IssuePointOrder( u, "attack", GetRectCenterX(gg_rct_Residence41), GetRectCenterY(gg_rct_Residence41) )
		call ItemAI(u)
		set u = null
	endfunction

	function PatrolToTown takes nothing returns nothing
		local unit u = GetEnumUnit()
		call IssuePointOrder( u, "attack", GetRandomReal(GetRectMinX(gg_rct_Town), GetRectMaxX(gg_rct_Town)), GetRandomReal(GetRectMinY(gg_rct_Town), GetRectMaxY(gg_rct_Town)) )
		call ItemAI(u)
		set u = null
	endfunction

	function AICommand takes player p, string order, real x, real y returns nothing
		local group g = CreateGroup()
		local unit u
		call GroupEnumUnitsOfPlayer(g,p,null)
		loop
			set u = FirstOfGroup(g)
			exitwhen u==null
			call IssuePointOrder(u,order,x+GetRandomReal(-200.0,200.0),y+GetRandomReal(-200.0,200.0))
			call GroupRemoveUnit(g,u)
		endloop
		call DestroyGroup(g)
		set g = null
	endfunction
		
		
	private function SmartGrenadesItemCheck takes nothing returns nothing
	   local integer i = GetItemTypeId(GetEnumItem())
	   if i=='I00Q' or i=='I00P' or i=='I00R' or i=='I00S' or i=='I00Y' or i=='I00Z' or i=='I00H' or i=='I00O' then
		   set udg_SmartGrenadesFail=1
	   endif
	endfunction

	private function SmartGrenadesConditions takes nothing returns boolean
		return GetUnitUserData(GetAttacker())==69 and GetRandomInt(1,40)==1
	endfunction

	private function SmartGrenades takes nothing returns nothing
		local unit u = GetAttacker()
		local unit u2 = GetTriggerUnit()
		local location l = GetUnitLoc(u2)
		local real x = GetUnitX(u2)
		local real y = GetUnitY(u2)
		local group g = AMGetUnitsInRange(600,l,Condition(function SelectAlliedUnits))
		local rect r = Rect(x-300.0,y-300.0,x+300.0,y+300.0)
		set udg_SmartGrenadesFail=0
		call EnumItemsInRect(r,null,function SmartGrenadesItemCheck)
		if FirstOfGroup(g)==null then
			if GetRandomInt(0,3)==1 then
				if GetRandomInt(1,3)==1 then
					call FieldChat(u, 5, "|cffcd950c" + GetUnitName(u) + "|r : Smoke!" )
				endif
				call UnitAddAbility(u,'A055') //Smoke Grenade
				call IssuePointOrder(u,"evileye",x,y)
				call PolledWait(3.)
				call UnitRemoveAbility(u,'A055')
			elseif udg_SmartGrenadesFail!=1 then
				if GetRandomInt(1,3)==1 then
					call FieldChat(u, 5, "|cffcd950c" + GetUnitName(u) + "|r : Fire in the Hole!" )
				endif
				call UnitAddAbility(u,'A038')
				call IssuePointOrder(u,"flamestrike",x,y)
				call EarShockArea(x,y,500)
				call PolledWait(3.)
				call UnitRemoveAbility(u,'A038')
			endif
		endif
		set udg_SmartGrenadesFail=0
		call RemoveRect(r)
		set r = null
		call DestroyGroup(g)
		set g = null
		call RemoveLocation(l)
		set l = null
		set u = null
		set u2 = null
	endfunction

	private function DynamicEvasionConditions takes nothing returns boolean
		local integer i = GetUnitPointValue(GetTriggerUnit())
		return GetUnitPointValue(GetAttacker())==50 and i!=99 and i!=98 and GetRandomInt(0,2)!=udg_EvasionCapability and GetUnitAbilityLevel(GetTriggerUnit(),'B001')<=0 and udg_ACA[GetConvertedPlayerId(GetOwningPlayer(GetTriggerUnit()))]
	endfunction

	private function DynamicEvasion takes nothing returns nothing
	   local unit u = GetTriggerUnit()
	   local real x = GetUnitX(u)
	   local real y = GetUnitY(u)
	   local real DistanceFactor = GetRandomReal(3.5,5.5)
	   if GetRandomInt(0,2)==1 then
		   call IssueImmediateOrder(u,"berserk")
	   endif
	   call IssuePointOrder( u,"move",x+(DistanceFactor*(x-GetUnitX(GetAttacker()))),y+(DistanceFactor*(y-GetUnitY(GetAttacker()))) )
	   set u = null
	endfunction

	globals
		private trigger SMART_GRENADES_T
		private trigger SMART_EVASION_T
	endglobals
	
	function SetDynamicEvasionEnabled takes boolean b returns nothing 
		if b then 
			call EnableTrigger(SMART_EVASION_T)
		else 
			call DisableTrigger(SMART_EVASION_T)
		endif
	endfunction 
	
	function SetSmartGrenadesEnabled takes boolean b returns nothing 
		if b then 
			call EnableTrigger(SMART_GRENADES_T)
		else 
			call DisableTrigger(SMART_GRENADES_T)
		endif
	endfunction 

	//===========================================================================
	private function init takes nothing returns nothing
		local trigger t  
		set t = CreateTrigger()
		call TriggerRegisterPlayerUnitEvent(t,Player(9),EVENT_PLAYER_UNIT_ATTACKED,null)
		call TriggerRegisterPlayerUnitEvent(t,Player(11),EVENT_PLAYER_UNIT_ATTACKED,null)
		call TriggerAddCondition(t, Condition(function DynamicEvasionConditions) )
		call TriggerAddAction(t,function DynamicEvasion)
		set SMART_EVASION_T = t 
		
		set t = CreateTrigger()
		call TriggerRegisterPlayerUnitEvent(t, Player(13), EVENT_PLAYER_UNIT_ATTACKED, null)
		call TriggerRegisterPlayerUnitEvent(t, Player(14), EVENT_PLAYER_UNIT_ATTACKED, null)
		call TriggerAddCondition( t, Condition( function SmartGrenadesConditions ) )
		call TriggerAddAction(t,function SmartGrenades)
		set SMART_GRENADES_T = t 
		
		set t = null
	endfunction

endlibrary